/**
  ******************************************************************************
  * @file    ds1302.c
  * @author  Dajin Li
  * @version V0.0.1
  * @date    08-08-2015 
  * @brief   Main program body
  *          
  ******************************************************************************
  * @attention
  *
  * <h2><center>&copy; KION(SZ) R&D Center
  *
  * Licensed under KION, (the "License");
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/

#include "stm32f10x_gpio.h"
#include "ds1302.h"
#include "global.h"
#include "menu.h"


u8 Settimebuf[7];
u8 Gettimebuf[7];

u8 ds1302_hour;

static u8 BCDH(u8 BCD_Data);
static u8 HBCD(u8 BCD_Data);



/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void Write_Ds1302_Byte(u8 data1302)
{
    u8 i;

	GPIO_InitTypeDef GPIO_InitStructure;

	/*Configure pins: PA8 LCD_CS*/
	/*Configure pins: PA12 Bell*/
	/*Configure pins: PA.10 VTXD, PA9 SL165*/
    // Pin12 ds1302 rst, pin14, ds1302 clock
	GPIO_InitStructure.GPIO_Pin =  DS1302_DATA;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
	GPIO_Init(DS1302_PORT, &GPIO_InitStructure);

    for(i = 0; i < 8; i++)
    {
        GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
        Delay(5);

        if(data1302 & 0x01) 
        {
            GPIO_SetBits(DS1302_PORT, DS1302_DATA);
        }
        else 
        {
            GPIO_ResetBits(DS1302_PORT, DS1302_DATA);
        }

        Delay(5);
        data1302 >>= 1;
        GPIO_SetBits(DS1302_PORT, DS1302_CLK);
        Delay(5);
    }
}
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void Write_Ds1302(u8 address,u8 dat)
{
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(10);
    Write_Ds1302_Byte(address);
    Write_Ds1302_Byte(dat);
    GPIO_SetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
} 
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

u8  Read_Ds1302_Byte(void)
{
    u8 i;
    u8 data1302 = 0;
	GPIO_InitTypeDef GPIO_InitStructure;

	/*Configure pins: PE.7,8,9,10 as KEY input*/
    // Key2 PC12, Key3 PC11, Key4 PC10
    // Pin13: ds1302 data
	GPIO_InitStructure.GPIO_Pin = DS1302_DATA;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
	GPIO_Init(DS1302_PORT, &GPIO_InitStructure);


    Delay(5);

    for(i = 0; i < 8; i++)
    {
        data1302 >>= 1;       
        GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
        Delay(5);
        if(GPIO_ReadInputDataBit(DS1302_PORT, DS1302_DATA))
        {
            data1302 |= 0x80;  
        }
        else
        {
            data1302 &= 0x7f;  
        }
        Delay(5);
        GPIO_SetBits(DS1302_PORT, DS1302_CLK);
        Delay(5);
    }
    return(data1302);       
}
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

u8 Read_Ds1302(u8 address)
{
    u8 DAT_1302 = 0x00;
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(10);
    Write_Ds1302_Byte(address);
    DAT_1302 = Read_Ds1302_Byte();
    GPIO_SetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
    return (DAT_1302);
}
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void Write_Ds1302_Bytes(u8 *pSecDa)
{
    u8 i;
    Write_Ds1302(DS1302_CTRL_WR_ADDR,0x00);      
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
    Write_Ds1302_Byte(0xbe);        
    for (i = 8; i > 0; i--)               
    {
        Write_Ds1302_Byte(*pSecDa);  
        pSecDa++;
    }
    GPIO_SetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
} 
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void Read_Ds1302_Bytes(u8 *pSecDa)
{
    u8 i;
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(10);
    Write_Ds1302_Byte(0xbf);         
    for (i = 8; i > 0; i--) 
    {
        *pSecDa = Read_Ds1302_Byte(); 
        pSecDa++;
    }
    GPIO_SetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
}
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void Write_Ds1302register_Bytes(u8 *pReDa)
{
    u8 i;
    Write_Ds1302(0x8e,0x00);      
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(10);
    Write_Ds1302_Byte(0xfe);       
    for (i = 31; i > 0; i--)             
    {
        Write_Ds1302_Byte(*pReDa); 
        pReDa++;
    }
    GPIO_SetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
} 
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void Read_Ds1302register_Bytes(u8 *pReDa)
{
    u8 i;
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(10);
    Write_Ds1302_Byte(0xff);         
    for (i = 31; i > 0; i--)             
    {
        *pReDa = Read_Ds1302_Byte();  
        pReDa++;
    }
    GPIO_SetBits(DS1302_PORT, DS1302_CLK);
    Delay(5);
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    Delay(5);
}
/**
* @brief	set 1302 start time.
* @param	none
* @note     none
* @retval   none
*/
void Set1302_starttime(u8 *pSecDa) 
{
   u8 i;
   u8 ucAddr = DS1302_SEC_WR_ADDR;  

   Write_Ds1302(DS1302_CTRL_WR_ADDR,0x00); // write wp       

   for(i = 7; i > 0; i--)
   { 
      Write_Ds1302(ucAddr, *pSecDa); 

      pSecDa++;
      ucAddr +=2;
   }
   Write_Ds1302(DS1302_CTRL_WR_ADDR,0x80);         
}
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void Get1302_ontime(u8 Gettimebuf[]) 
{
   u8 i;
   u8 onAddr = 0x81;
  // u8 j,sec=0;
   for (i=0;i<7;i++)
   {
      Gettimebuf[i] = Read_Ds1302(onAddr);  
	  //sec =  Gettimebuf[i];
	  //j = sec >> 4;                        
	  //j *=10;
	  //sec = sec & 0x0f;
	  //sec += j;
	  //Gettimebuf[i] = sec ;
      onAddr += 2;
   }
}
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void DS1302_writeymdhm(void)
{ 
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(10);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Write_Ds1302(0x8e, 0x00);      
    //Write_Ds1302(0x80, Gettimebuf[0]);     
	Write_Ds1302(0x82, Gettimebuf[1]);      

	Gettimebuf[2]=Gettimebuf[2]|0x80;
	Write_Ds1302(0x84, Gettimebuf[2]);      
//	Write_Ds1302(0x86, Gettimebuf[3]);      
//	Write_Ds1302(0x88, Gettimebuf[4]);      
//	Write_Ds1302(0x8c, Gettimebuf[6]);      
    Write_Ds1302(0x8e, 0x80);      
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
}

/**
* @brief	write hour data.
* @param	none
* @note     none
* @retval   none
*/
void Ds1302_writehourdata(u8 Address,u8 Gettimebuf1)
{ 
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(10);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Write_Ds1302(DS1302_CTRL_WR_ADDR, 0x00);               
	Write_Ds1302(DS1302_MIN_WR_ADDR, Gettimebuf1);      
    Write_Ds1302(DS1302_CTRL_WR_ADDR, 0x80);               
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
}
/**
* @brief	write data.
* @param	none
* @note     none
* @retval   none
*/
void Ds1302_writedata(u8 Address,u8 Gettimebuf2)
{ 
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
	Delay(10);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Write_Ds1302(DS1302_CTRL_WR_ADDR, 0x00);               
	Write_Ds1302(Address, Gettimebuf2);      
    Write_Ds1302(DS1302_CTRL_WR_ADDR, 0x80);               
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
}

/**
* @brief	write second data.
* @param	none
* @note     none
* @retval   none
*/

void Ds1302_writeseconddata(u8 Address,u8 Gettimebuf1)
{ 
    GPIO_SetBits(DS1302_PORT, DS1302_RST);
    Delay(10);
    GPIO_ResetBits(DS1302_PORT, DS1302_CLK);
    Write_Ds1302(DS1302_CTRL_WR_ADDR, 0x00);               
	Write_Ds1302(DS1302_SEC_WR_ADDR, Gettimebuf1);      
    Write_Ds1302(DS1302_CTRL_WR_ADDR, 0x80);               
    GPIO_ResetBits(DS1302_PORT, DS1302_RST);
}

/**
* @brief	read year.
* @param	none
* @note     none
* @retval   none
*/

void ReadYearData(void)
{
    u8 temp = 0x00;
    temp  = Read_Ds1302( DS1302_YEAR_RD_ADDR);
    temp = BCDH(temp);
    date_year = temp;
}

/**
* @brief	read day 1-7.
* @param	none
* @note     none
* @retval   none
*/

void ReadDayData(void)
{
    u8 temp = 0x00;
    temp  = Read_Ds1302( DS1302_DAY_WR_ADDR);
    date_week = temp;
}


/**
* @brief	read month.
* @param	none
* @note     none
* @retval   none
*/

void ReadMonthData(void)
{
    u8 temp = 0x00;
    temp  = Read_Ds1302( DS1302_MON_RD_ADDR);
    temp &= 0x1F;
    temp = BCDH(temp);
    date_month = temp;
}

/**
* @brief	read date.
* @param	none
* @note     none
* @retval   none
*/

void ReadDateData(void)
{
    u8 temp = 0x00;
    temp  = Read_Ds1302( DS1302_DATE_RD_ADDR);
    temp &= 0x7F;
    temp = BCDH(temp);
    date_day = temp;
}


/**
* @brief	read seconds.
* @param	none
* @note     none
* @retval   none
*/

void ReadSecondsData(void)
{
    u8 temp = 0x00;

    temp  = Read_Ds1302( DS1302_SEC_RD_ADDR);
    temp &= 0x7F;

    temp = BCDH(temp);

    if(temp > 59)
    {
        temp = 59;
    }

    date_seconds = temp;
}

/**
* @brief	read minutes.
* @param	none
* @note     none
* @retval   none
*/

void ReadMinuteData(void)
{
    u8 temp = 0x00;

    temp  = Read_Ds1302( DS1302_MIN_RD_ADDR);
    temp &= 0x7F;

    temp = BCDH(temp);

    if(temp > 59)
    {
        temp = 59;
    }
    date_minutes = temp;
}
/**
* @brief	read hours.
* @param	none
* @note     none
* @retval   none
*/
void ReadHourData(void)
{
    u8 temp = Read_Ds1302( DS1302_HOUR_RD_ADDR);

    ds1302_hour = temp;

    if((temp & 0x20) == 0x00)
    {
        date_am = 0x00;
    }
    else
    {
        date_am = 0x01;
    }

    if((temp & 0x80) == 0x00)
    {
        hour_format_12H = 0x00;
        temp &= 0x3F;
        temp = BCDH(temp);
        if(temp > 23)
        {
            temp = 23;
        }
    }
    else
    {
        hour_format_12H = 0x01;
        temp &= 0x1F;
        temp = BCDH(temp);
        if(temp > 11)
        {
            temp = 11;
        }
    }
    date_hours = temp;
}

/**
* @brief	bcd to hex.
* @param	none
* @note     none
* @retval   none
*/

u8 BCDH(u8 BCD_Data)
{  
	u8  Temp;
	Temp = (BCD_Data >> 4) * 10 + BCD_Data % 16;
	return(Temp);
}

/**
* @brief	hex to bcd.
* @param	none
* @note     none
* @retval   none
*/


u8 HBCD(u8 Hex_BCD)
{ 
	u8 Temp;
	u8 BCD_Data; 

	Temp = Hex_BCD % 100;	
	BCD_Data = (Hex_BCD / 100) << 8;
	BCD_Data = BCD_Data | ((Temp / 10) << 4);
	BCD_Data = BCD_Data | (Temp % 10);
	return(BCD_Data);
}
/**
* @brief	save param to EEPROM.
* @param	none
* @note     none
* @retval   none
*/

void DS1302_Initial(void)
{   
    u8 tempint = 0;

    Gettimebuf[6] = 0x0;  
    Gettimebuf[5] = 0x0;  
    Gettimebuf[4] = 0x0;  
    Gettimebuf[3] = 0x0;  
    Gettimebuf[2] = 0x0;  
    Gettimebuf[1] = 0x0;  
    Gettimebuf[0] = 0x30; 

    Settimebuf[6] = 0x15;   // year 0-99
    Settimebuf[5] = 0x02;   // day, 1-7
    Settimebuf[4] = 0x08;   // month 1-12
    Settimebuf[3] = 0x09;   // date 01-28/29/30/31
    Settimebuf[2] = 0x89;   // hours, bit7 1: 12 hour format, am 9, 10001001 pm 9: 10101001 bit5 0:am, 1 pm
    Settimebuf[1] = 0x58;   // minutes 0-59
    Settimebuf[0] = 0x00;   // seconds 0-59


    tempint = Read_Ds1302( DS1302_RAM0_RD_ADDR );

    if(tempint != DS1302_RAM0_INIT_VAL) 
    {              
        GPIO_SetBits(DS1302_PORT, DS1302_RST);
        Delay(10);
        GPIO_ResetBits(DS1302_PORT, DS1302_CLK);

        Write_Ds1302(DS1302_CTRL_WR_ADDR, 0x00);   // disable write protect  
        Write_Ds1302(DS1302_SEC_WR_ADDR, 0x00);      
        Write_Ds1302(DS1302_CHARGER_WR_ADDR, 0xa6);      
        Write_Ds1302(DS1302_RAM0_WR_ADDR, DS1302_RAM0_INIT_VAL);      
        Write_Ds1302(DS1302_CTRL_WR_ADDR, 0x80);   // enable write protect   
        Set1302_starttime( Settimebuf ); 
        GPIO_ResetBits(DS1302_PORT, DS1302_RST);
    } 
}

/**
  * @brief  Display the current time on the Hyperterminal.
  * @param  None
  * @retval None
  */
void DS1302_TimeShow(void)
{
    if(set_time_flag == 0)
    {
        ReadSecondsData();
        ReadMinuteData();
        ReadHourData();
    }
}

/**
  * @brief  Display the current date on the Hyperterminal.
  * @param  None
  * @retval None
  */
void DS1302_DateShow(void)
{
    if(set_time_flag == 0)
    {
        ReadDateData();
        ReadYearData();
        ReadMonthData();
        ReadDayData();
    }
}
/**
  * @brief  Display the current time on the Hyperterminal.
  * @param  None
  * @retval None
  */
void DS1302_TimeSet(void)
{
    u8 bcd_value;
     
    if(regulate_time_flag == RTC_SET_SECONDS)
    {
        bcd_value = HBCD(date_seconds);
        Ds1302_writedata(DS1302_SEC_WR_ADDR, bcd_value);
    }
    else if(regulate_time_flag == RTC_SET_MINUTES)
    {
        bcd_value = HBCD(date_minutes);
        Ds1302_writedata(DS1302_MIN_WR_ADDR, bcd_value);
    }
    else if(regulate_time_flag == RTC_SET_HOURS)
    {
        bcd_value = HBCD(date_hours);

        if(hour_format_12H)
        {
            ds1302_hour &= 0xE0;
        }
        else
        {
            ds1302_hour &= 0xC0;
        }
        ds1302_hour |= bcd_value;

        Ds1302_writedata(DS1302_HOUR_WR_ADDR, ds1302_hour);
    }
    else if(regulate_time_flag == RTC_SET_PM)
    {
        ds1302_hour &= 0xDF;
        ds1302_hour |= (date_am << 5);
        Ds1302_writedata(DS1302_HOUR_WR_ADDR, ds1302_hour);
    }
    else if(regulate_time_flag == RTC_SET_HOUR_FORMAT)
    {
        ds1302_hour &= 0x7F;
        ds1302_hour |= (hour_format_12H << 7);  // 1, 12 hour format
        Ds1302_writedata(DS1302_HOUR_WR_ADDR, ds1302_hour);
    }
    else if(regulate_time_flag == RTC_SET_MONTH)
    {
        bcd_value = HBCD(date_month);
        Ds1302_writedata(DS1302_MON_WR_ADDR, bcd_value);
    }
    else if(regulate_time_flag == RTC_SET_DATE)
    {
        bcd_value = HBCD(date_day);
        Ds1302_writedata(DS1302_DATE_WR_ADDR, bcd_value);
    }
    else if(regulate_time_flag == RTC_SET_YEARS)
    {
        bcd_value = HBCD(date_year);
        Ds1302_writedata(DS1302_YEAR_WR_ADDR, bcd_value);
    }
}




